package blueq.dao.mongodb.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import blueq.entity.mongo.Tree;

import com.mongodb.WriteResult;

/**
 * MongoDB base DAO class implementation.
 * This class supply general methods that operate mongoDB. 
 * @author sail
 * @version 0.1
 * @since 2014-05-01
 */
@Repository("mongoDbDao")
public class MongoDBDaoImpl {
	@Resource(name="mongoTemplate")
	private MongoTemplate mongoTemplate;

	public void setMongoTemplate(MongoTemplate mongoTemplate) {
		this.mongoTemplate = mongoTemplate;
	}

	/**
	 * Get all objects in a specified collection.
	 * @param clazz 
	 * @return
	 */
	public <T> List<T> getAllObjects(Class<T> clazz) {
		return mongoTemplate.findAll(clazz);
	}
	
	public <T> List<T> getAllObjects(Class<T> clazz, String collectionName){
		return mongoTemplate.findAll(clazz, collectionName);
	}

	public <T> List<T> findByQuery(Query query, Class<T> clazz) {
		return mongoTemplate.find(query, clazz);
		
	}
	
	
	public <T> List<T> findByQuery(Query query, Class<T> clazz, String collection) {
		return mongoTemplate.find(query, clazz, collection);
	}
	
	/**
	 * Insert the object into the collection for the entity type of the object to save. 
	 * The object is converted to the MongoDB native representation using an instance
	 *  of {@see MongoConverter}. 
	 * @param t
	 */
	public <T> void insertObject(T t) {
		mongoTemplate.insert(t);
	}

	/**
	 * Get an object that using a specified id.
	 * @param id
	 * @param clazz
	 * @return
	 */
	public <T> T getObject(String id, Class<T> clazz) {
		return mongoTemplate.findOne(new Query(Criteria.where("id").is(id)),
				clazz);
	}
	
	public <T> T findOne(String tableName, Criteria criteria, Class<T> clazz) {
		return mongoTemplate.findOne(new Query(criteria), clazz);
	}

	/**
	 * Updates a{<span class="referer">@link</span>  Tree} name for a particular id.
	 */
	public <T> WriteResult updateObject(String id, String name, Class<T> clazz) {
		return mongoTemplate.updateFirst(
				new Query(Criteria.where("id").is(id)),
				Update.update("name", name), clazz);
	}

	/**
	 * Delete a {<span class="referer">@link</span>  Tree} for a particular id.
	 */
	public void deleteObject(String id) {
		mongoTemplate
				.remove(new Query(Criteria.where("id").is(id)), Tree.class);
	}
	
	/**
	 * Insert the object into the collection for the entity type of the object to save. 
	 * The object is converted to the MongoDB native representation using an instance 
	 * of {@see MongoConverter}. 
	 * @param t
	 */
	public <T> void saveObject(T t) {
		mongoTemplate.save(t);
	}

	/**
	 * Create a {<span class="referer">@link</span>  Tree} collection if the collection does not already
	 * exists
	 */
	public <T> void createCollection(Class<T> clazz) {
		if (!mongoTemplate.collectionExists(clazz)) {
			mongoTemplate.createCollection(clazz);
		}
	}

	/**
	 * Drops the {<span class="referer">@link</span>  Tree} collection if the collection does already exists
	 */
	public <T> void dropCollection(Class<T> clazz) {
		if (mongoTemplate.collectionExists(clazz)) {
			mongoTemplate.dropCollection(clazz);
		}
	}
	
	/**
	 * 根据参数-值 返回查询结果
	 * @param clazz
	 * @param columns
	 * @param params
	 * @return
	 */
	public <T> List<T> findByParams(Class<T> clazz, String[] columns, Object[] params ) {
		//if the lenth of columns and params mismatch
		if(columns.length != params.length || columns.length <=0 || columns.length <=0) {
			//throw new Exception("Lenth of parameters mismatch the columns");
			return null;
		}
		
		Criteria criteria = Criteria.where(columns[0]).is(params[0]);
		for (int i = 1; i < params.length; i++) {
			criteria.and(columns[i]).is(params[i]);
		}
		List<T> result = mongoTemplate.find(new Query(criteria), clazz);
		return result;
	}
	
	/**
	 * 根据id查找记录
	 * @param id
	 * @param clazz
	 * @return
	 */
	public <T> T findById(String id, Class<T> clazz) {
		//return mongoTemplate.findById(id, clazz);
		return mongoTemplate.findOne(new Query(Criteria.where("_id").is(id)),clazz );
	}
}
